/**
 * Chessboard.
 * 
 * @author Brian Boadi, Antoine Domenger
 * @version 1.0
 */

package lp.chess;

public class Chessboard {
	//- ATTRIBUTE(S) --------------------------------------------------------------------------
	
	/**
	 * The squares on the chessboard.
	 */
	private Piece[] m_cases;
	
	//-----------------------------------------------------------------------------------------
	
	//- CONSTRUCTOR(S) ------------------------------------------------------------------------
	
	/**
 	 * Default constructor.
 	 * Initializes an empty chessboard.
 	 */
	public Chessboard() {
		setCases(new Piece[64]);
	}
	
	/**
	 * Copy constructor.
	 * Initializes a new chessboard from a given one.
	 * 
	 * @param cb the chessboard to copy in the new one.
	 */
	public Chessboard(Chessboard cb) {
		int i;
		
		setCases(new Piece[64]);
		
		if(cb != null) {
			for(i = 0 ; i < 64 ; i++) {
				if(cb.getCases()[i] != null) m_cases[i] = cb.getCases()[i].getCopy();
			}
		}
	}
	
	//-----------------------------------------------------------------------------------------
	
	//- GETTER(S) AND SETTER(S) ---------------------------------------------------------------
	
	/**
	 * Get the cases of the chessboard.
	 *
	 * @return the cases of the chessboard.
	 */
	public Piece[] getCases() {
		return m_cases;
	}
	
	/**
	 * Set the cases of the chessboard.
	 *
	 * @param cases the new cases of the chessboard.
	 */
	public void setCases(Piece[] cases) {
		m_cases = cases;
	}
	
	//-----------------------------------------------------------------------------------------
	
	//- OTHER METHOD(S) -----------------------------------------------------------------------
	
	/**
	 * Get the piece that is at the given position.
	 *
	 * @param x an integer between 1 and 8
	 * @param y an integer between 1 and 8
	 *
	 * @return null if there is no piece on this square, or a pointer to this piece if it has been found
	 */
	public Piece getPiece(int x, int y) {
		int tmp = (y - 1) * 8 + (x - 1);
		Piece p = null;
		
		if(tmp < 0 || tmp > 63) // The position is not valid.
		{
			System.out.println("Invalid position...\n");
		}
		else
		{
			p = getCases()[tmp];
		}
		
		return p;
	}
	
	/**
	 * Checks if the given case is in or outside the chessboard.
	 * 
	 * @param x the x coordinate to check.
	 * @param y the y coordinate to check.
	 * @return true if the case is on the chessboard, false if it is out of it.
	 */
	public boolean isOutOfRange(int x , int y) {
		boolean isOutOfRange = true;
		
		if(x < 1 || x > 8 || y < 1 || y > 8)
		{
			System.out.println("Invalid position...");
			isOutOfRange = false;
		}
		
		return isOutOfRange;
	}
	
	/**
	 * Places a piece on the chessboard at the position specified by the piece itself.
	 *
	 * @param p a pointer to the piece we want to place
	 *
	 * @return 'true' if it went well, or 'false' if there was somehow a problem
	 * (case taken, invalid position, empty piece)
	 */
	public boolean place(Piece p) {
		boolean canBePlaced = true;
		int x = 0;
		int y = 0;

		if(p == null)	// The piece is NULL.
		{
			System.out.println("Null piece...\n");
			canBePlaced = false;
		}
		else
		{
			x = p.getX();
			y = p.getY();
		}

		if(canBePlaced)	// The piece can be placed as no problem occurred.
		{
			// Now that any problem has been eliminated, we can actually place the piece on the chessboard :
			m_cases[(y - 1) * 8 + (x - 1)] = p;
			canBePlaced = true;

		}

		return canBePlaced;
	}
	
	/**
	 * Moves a piece on the chessboard from its position to another.
	 *
	 * @param p a pointer to the piece
	 * @param x an integer between 1 and 8
	 * @param y an integer between 1 and 8
	 *
	 * @return 'true' if it was placed without a problem, or 'false' if there was a problem
	 * (case taken, invalid position, empty piece, piece not at the right place on the chessboard)
	 */
	public boolean move(Piece p, int x, int y) {
		boolean canBeMoved = true;
		int oldX = 0;
		int oldY = 0;

		if(p == null)	// The piece is NULL.
		{
			System.out.println("Null piece...\n");
			canBeMoved = false;
		}

		if(canBeMoved)	// The piece is not NULL, then we can try to move it.
		{
			oldX = p.getX();
			oldY = p.getY();

			p.setX(x);
			p.setY(y);
			
			canBeMoved = place(p);
		}

		if(!canBeMoved)	// The piece was not placed correctly, so we must restore i to its old square.
		{
			p.setX(oldX);
			p.setY(oldY);
		}
		else	// The piece was placed correctly, so we must remove it from its old square.
		{
			removePiece(oldX, oldY);
		}

		return canBeMoved;
	}
	
	/**
	 * Removes the piece at the given position.
	 *
	 * @param x an integer between 1 and 8
	 * @param y an integer between 1 and 8
	 *
	 * @return null if there is no piece on this square, or a pointer to the piece if it was removed
	 */
	public Piece removePiece(int x, int y) {
		Piece removedPiece = getPiece(x, y);

		if(removedPiece != null)	// There is a piece in this square.
		{
			m_cases[(y-1)*8+(x-1)] = null;
		}

		return removedPiece;
	}
	
	//-----------------------------------------------------------------------------------------

	// DISPLAY METHOD(S) ----------------------------------------------------------------------
	
	/**
	 * Displays the chessboard with '#' for the black squares and '.' for the white ones if those are empty.
	 * If there is a piece on a square, it would be a capital 'W' for a white one and a B for a black one.
	 */
  	public void display() {
  		System.out.print("\n" + "  12345678" + "\n");
  		
  		for(int y = 1 ; y <= 8 ; ++y)
  		{
  			System.out.print(y + " ");
  			
  			for(int x = 1 ; x <= 8 ; ++x)
  			{
  				char c;
  				Piece p = getPiece(x, y);
  				
  				if(p == null) c = ((x + y) % 2) == 0 ? '#' : '.';
  				else c = p.getType();
  				
  				System.out.print(c);
  			}
  			
  			System.out.print(" " + y + "\n");
  		}
  		
  		System.out.print("  12345678" + "\n");
  	}
	
	//-----------------------------------------------------------------------------------------
}
